package cn.chendd.patch.ui.adapters.enums;

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.filechooser.FileSystemView;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.text.JTextComponent;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.reflect.ConstructorUtils;

import cn.chendd.patch.enums.EnumExcept;
import cn.chendd.patch.enums.EnumProperties;
import cn.chendd.patch.ui.MainFrame;
import cn.chendd.patch.ui.adapters.impls.OtherImpl;
import cn.chendd.patch.ui.adapters.impls.PathAdapter;
import cn.chendd.patch.ui.components.JTextFieldRightIcon;
import cn.chendd.patch.ui.components.table.SimpleDataTable;
import cn.chendd.utils.CommonUtil;
import cn.chendd.utils.LogUtil;
import cn.chendd.utils.MyImageIcon;
import cn.chendd.utils.PropertiesUtil;

public class FileListPanel extends TabPanel {

	private static final long serialVersionUID = -6052940236838941363L;

	private JLabel fileListLabel = new JLabel("选择列表文件：");
	private JTextFieldRightIcon fileListText = new JTextFieldRightIcon("file_obj.png");
	private JButton fileListButton = new JButton("浏览...");
	private JLabel compileLabel = new JLabel("选择编译目录：");
	private JTextFieldRightIcon compileText = new JTextFieldRightIcon("open-task.gif");
	private JButton compileButton = new JButton("浏览...");
	private JButton loadButton = new JButton("载入文件" , new MyImageIcon("reload.png"));
	private JButton createButton = new JButton("生成补丁" , new MyImageIcon("resource_persp.gif"));
	

	private int elementHeight = 100;
	private int tableWidth = super.mainFrame.windowWidth - 40;
	private int tableHeight = super.mainFrame.windowHeight - elementHeight - 120;
	
	
	private JPopupMenu rightMenu = null;
	
	private JPopupMenu inputRightMenu = null;//input框的右键功能
	
	public SimpleDataTable dataTable = new SimpleDataTable(){
		
		private static final long serialVersionUID = 1L;
		@Override
		public Integer[] getColumnWidth() {
			return new Integer[]{
				60, tableWidth - 60 - 80 - 20 , 80
			};
		}
		
		@Override
		public String[] getHeaders() {
			return new String[]{
				"序号" , "文件路径" , "操作"
			};
		}

		@Override
		public boolean isCellEditable(int i, int j) {
			return false;
		}

		@Override
		protected void tableRender() {
			Integer columnWidths[] = this.getColumnWidth();
			int columnCount = this.getColumnModel().getColumnCount();
			if(columnWidths != null && columnCount != 0){
				//设置最后一列居中显示
				DefaultTableCellRenderer centerRender = new DefaultTableCellRenderer();
				centerRender.setHorizontalAlignment(SwingConstants.CENTER);
				this.getColumnModel().getColumn(this.getHeaders().length - 1).setCellRenderer(centerRender);
			}
			
		}
		
	};
	
	public FileListPanel(MainFrame mainFrame, JTabbedPane tab) {
		super(mainFrame, tab);
	}

	@Override
	protected void initElement() {
		
		JPanel elementPanel = new JPanel();
		elementPanel.setLayout(null);
		elementPanel.setBounds(0, 0, super.mainFrame.windowWidth, elementHeight);
		fileListLabel.setBounds(22, 10, 100, 25);
		elementPanel.add(fileListLabel);
		fileListText.setBounds(110, 10, 300, 25);
		elementPanel.add(fileListText);
		fileListButton.setBounds(420, 10, 70, 25);
		elementPanel.add(fileListButton);
		compileLabel.setBounds(22, 50, 100, 25);
		elementPanel.add(compileLabel);
		compileText.setBounds(110, 50, 300, 25);
		elementPanel.add(compileText);
		compileButton.setBounds(420, 50, 70, 25);
		elementPanel.add(compileButton);
		//选择文件
		fileListButton.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent event) {
				String filePath = CommonUtil.getFileChooser(FileListPanel.this , "选择文件列表：", "txt","csv","xls","xlsx");
				if(filePath != null){
					fileListText.setText(filePath);
					loadButton.setEnabled(true);
				} else {
					loadButton.setEnabled(false);
					fileListText.setText("");
				}
			}
			
		});
		//路径失去焦点事件
		fileListText.addFocusListener(new FocusAdapter() {
			@Override
			public void focusLost(FocusEvent event) {
				String text = fileListText.getText();
				if(StringUtils.isNotBlank(text)){
					loadButton.setEnabled(true);
				} else {
					loadButton.setEnabled(false);
				}
			}
			
		});
		//路径鼠标右键
		fileListText.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent event) {
				if(event.getButton() == MouseEvent.BUTTON3){
					getRigtMenuByInput(fileListText).show(fileListText, event.getX(), event.getY());
				}
			}
		});
		
		//选择目录
		compileButton.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent event) {
				String filePath = CommonUtil.getDirectoryChooser(FileListPanel.this, "选择文件夹：", "选中");
				if(filePath != null){
					compileText.setText(filePath);
					createButton.setEnabled(true);
				} else {
					createButton.setEnabled(false);
					compileText.setText("");
				}
			}
			
		});
		
		loadButton.setEnabled(false);
		loadButton.setBounds(510, 9, 90, 26);
		elementPanel.add(loadButton);
		//载入文件按钮处理
		loadButton.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent event) {
				if(loadButton.isEnabled()){
					//载入文件列表
					loadFile2Table();
				}
			}
		});
		createButton.setEnabled(false);
		createButton.setBounds(510, 49, 90, 26);
		elementPanel.add(createButton);
		//载入文件按钮处理
		createButton.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent event) {
				if(createButton.isEnabled()){
					//载入文件列表
					createPatchs();
				}
			}
		});
		//路径失去焦点事件
		compileText.addFocusListener(new FocusAdapter() {
			@Override
			public void focusLost(FocusEvent event) {
				String text = compileText.getText();
				if(StringUtils.isNotBlank(text)){
					createButton.setEnabled(true);
				} else {
					createButton.setEnabled(false);
				}
			}
		});
		//路径鼠标右键
		compileText.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent event) {
				if(event.getButton() == MouseEvent.BUTTON3){
					getRigtMenuByInput(compileText).show(compileText, event.getX(), event.getY());
				}
			}
		});
		
		dataTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);//表格单行选择
		dataTable.setCellSelectionEnabled(false);//设置不让选中行的背景色
		dataTable.getTableHeader().setReorderingAllowed(false);//不可整列拖动
		dataTable.setIntercellSpacing(new Dimension());
		
		dataTable.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent event) {
				if(event.getButton() == MouseEvent.BUTTON3){
					//判断点击处为表格
					int focusRowIndex = dataTable.rowAtPoint(event.getPoint());
					if(focusRowIndex == -1){
						return;
					}
					//将表格右键选中的行作为选中行
					dataTable.setRowSelectionAllowed(true);
					dataTable.setRowSelectionInterval(focusRowIndex, focusRowIndex);
					getRightMenu().show(dataTable, event.getX(), event.getY());
				}
			}
		});
		JScrollPane dataPanel = new JScrollPane();
		dataPanel.setViewportView(dataTable);
		dataPanel.setBounds(18, 100, tableWidth, tableHeight);
		
		dataTable.fillDataMapList(new ArrayList<LinkedHashMap<String , Object>>());
		
		this.add(elementPanel);
		this.add(dataPanel);
	}
	
	protected void createPatchs() {
		String folderPath = compileText.getText().trim();
		if(StringUtils.isBlank(folderPath)){
			JOptionPane.showMessageDialog(null, "请先选编译目录!", "警告：", JOptionPane.ERROR_MESSAGE);
			return;
		}
		File file = new File(folderPath);
		if(! file.exists()){
			JOptionPane.showMessageDialog(null, "选择目录不存在!", "警告：", JOptionPane.ERROR_MESSAGE);
			return;
		}
		if(! file.isDirectory()){
			JOptionPane.showMessageDialog(null, "选择路径不为文件夹!", "警告：", JOptionPane.ERROR_MESSAGE);
			return;
		}
		int lastColumn = dataTable.getHeaders().length - 1;
		if(lastColumn < 1){
			JOptionPane.showMessageDialog(null, "没有要生的数据!", "警告：", JOptionPane.ERROR_MESSAGE);
			return;
		}
		int rowCount = dataTable.getRowCount();
		String dateTime = new SimpleDateFormat("yyyyMMddHHmm").format(new Date());
		FileSystemView systemView = FileSystemView.getFileSystemView();
		File dstFolder = new File(systemView.getHomeDirectory() + File.separator + dateTime + File.separator + "code");
		if(dstFolder.exists()){
			new Dialog(5 , "警告" , "已经存在当前时分的文件夹了,等一秒再试!").execute();
			return;
		}
		dstFolder.mkdirs();//创建输出目录
		try {
			final String value = EnumExcept.EXCEPT.getKey();
			for (int i = 0; i < rowCount; i++) {
				String path = (String) dataTable.getValueAt(i, 1);
				String status = (String) dataTable.getValueAt(i, 2);
				if(value.equals(status)){
					continue;
				}
				addPathAdapter(path, compileText.getText(), dstFolder);
			}
			new Dialog(5 , "提示" , "补丁包 [" + dateTime + "] 已生成，请自行核对正确性！").execute();
		} catch (Exception e) {
			LogUtil.error(e);//记录日志
			new Dialog(5 , "警告" , "发生错误了...").execute();
			try {
				FileUtils.deleteDirectory(dstFolder);
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
		
	}
	
	public static void addPathAdapter(String path , String compileFolder , File dstFolder) throws Exception{
		
		Properties props = new PropertiesUtil(EnumProperties.CONFIG_PROPERTIES).getProperties();
		List<EnumParamLable> enumParamLable = EnumParamLable.getValuesList(EnumParamLable.BASIC_PARAM_WEBCONTENT.getParamType());
		boolean existFlag = false;
		for (EnumParamLable label : enumParamLable) {
			String propCode = label.getLableTextProperCode();
			String implement = ".implement";
			if(StringUtils.endsWith(propCode, implement) == false){
				continue;
			}
			String name = PathAdapter.class.getName();
			String simpleName = PathAdapter.class.getSimpleName();
			String packageName = StringUtils.substring(name , 0, name.length() - simpleName.length());
			String className = packageName + props.getProperty(propCode);
			try {
				String regex = props.getProperty(propCode.substring(0 , propCode.length() - implement.length()));
				PathAdapter adapter = (PathAdapter) ConstructorUtils.invokeConstructor(Class.forName(className), 
					new Object[]{compileFolder , regex , dstFolder , path});
				boolean flag = adapter.patchFilterRule();
				if(flag){
					existFlag = true;
					adapter.patchByPath();
				}
			} catch (Exception e) {
				LogUtil.error("实现类 [" + className + "] 发生错误", e);
				throw new Exception(e);
			}
		}
		if(existFlag == false){
			try {
				PathAdapter adapter = (PathAdapter) ConstructorUtils.invokeConstructor(OtherImpl.class, 
						new Object[]{compileFolder , "", dstFolder , path});
				adapter.patchByPath();
			} catch (Exception e) {
				LogUtil.error("默认实现类 [OtherImpl] 调用出现错误", e);
				throw new Exception(e);
			}
		}
	}

	private void loadFile2Table() {
		String fileListPath = fileListText.getText().trim();
		if(StringUtils.isBlank(fileListPath)){
			JOptionPane.showMessageDialog(null, "请先选择列表文件!", "警告：", JOptionPane.ERROR_MESSAGE);
			return;
		}
		File file = new File(fileListPath);
		if(! file.exists()){
			JOptionPane.showMessageDialog(null, "选择列表文件不存在!", "警告：", JOptionPane.ERROR_MESSAGE);
			return;
		}
		List<String> dataList = readFileList(file);
		if(dataList == null || dataList.isEmpty()){
			return;
		}
		//将数据填充至dataTable
		int index = 0;
		List<LinkedHashMap<String , Object>> list = new ArrayList<LinkedHashMap<String , Object>>();
		for (String filePath : dataList) {
			LinkedHashMap<String , Object> map = new LinkedHashMap<String , Object>();
			map.put("index", ++index);
			map.put("filePath", filePath);
			list.add(map);
		}
		dataTable.fillDataMapList(list);
	}

	private List<String> readFileList(File file) {
		List<String> fileList = null;
		try {
			fileList = CommonUtil.getListByFile(file, 0);
		} catch (IOException e) {
			String message = "读取文件数据出现错误";
			JOptionPane.showMessageDialog(null, message + "!", "警告：", JOptionPane.ERROR_MESSAGE);
			LogUtil.error(message + "：", e);
		}
		return fileList;
	}
	
	private JPopupMenu getRigtMenuByInput(final JTextComponent component) {
		
		inputRightMenu = new JPopupMenu();
		final JMenuItem copyItem = new JMenuItem(new MyImageIcon("copy.png"));
		copyItem.setText("粘贴");
		Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
		String text = null;
		if(clipboard != null) {
			Transferable trans = clipboard.getContents(null);
			if(trans != null) {
				 // 判断剪贴板中的内容是否支持文本
				if (trans.isDataFlavorSupported(DataFlavor.stringFlavor)) {
					try {
						text = (String) trans.getTransferData(DataFlavor.stringFlavor);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
		if(text == null) {
			copyItem.setEnabled(false);
		}
		final String value = text;
		
		copyItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				if(copyItem.isEnabled() && value != null) {
					component.setText(value);
				}
			}
		});
		inputRightMenu.add(copyItem);
		return inputRightMenu;
	}
	
	private JPopupMenu getRightMenu(){
		
		final int selectRowIndex = dataTable.getSelectedRow();
		final int lastColumn = dataTable.getHeaders().length - 1;
		
		String text = (String) dataTable.getValueAt(selectRowIndex, lastColumn);
		final String value = EnumExcept.EXCEPT.getKey();
		
		rightMenu = new JPopupMenu();
		final JMenuItem normalItem = new JMenuItem(new MyImageIcon("except.gif"));
		normalItem.setText("忽略");
		normalItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				if(normalItem.isEnabled()){
					dataTable.setValueAt(value, selectRowIndex, lastColumn);
					new Dialog(2 , "提示" , "已设置忽略！").execute();
				}
				
			}
		});
		if(value.equals(text)){
			normalItem.setEnabled(false);
		}
		rightMenu.add(normalItem);
		rightMenu.addSeparator();
		final JMenuItem cancalItem = new JMenuItem(new MyImageIcon("cancal_except.gif"));
		cancalItem.setText("取消忽略");
		cancalItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				if(cancalItem.isEnabled()){
					dataTable.setValueAt("", selectRowIndex, lastColumn);
					new Dialog(2 , "提示" , "已取消忽略！").execute();
				}
			}
		});
		rightMenu.add(cancalItem);
		if(StringUtils.isEmpty(text)){
			cancalItem.setEnabled(false);
		}
		return rightMenu;
	}
	
	public class Dialog {
		
		private int num ;
		private String title , text;
		
		public Dialog(int num , String title , String text){
			this.num = num;
			this.title = title;
			this.text = text;
		}
		
		public void execute(){
			final JOptionPane op = new JOptionPane(text , JOptionPane.INFORMATION_MESSAGE);
			final JDialog dialog = op.createDialog(title + "：");
			Timer timer = new Timer();
			timer.schedule(new TimerTask() {
				@Override
				public void run() {
					for(int i=num ; i >= 1 ; i--){
						dialog.setTitle(title + "（" + i + "）：");
						try {
							Thread.sleep(1000L);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
					dialog.setVisible(false);
					dialog.dispose();
				}
			}, 0);
			dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
			dialog.setAlwaysOnTop(true);
			dialog.setVisible(true);
		}
		
	}
	
}
